package odgs;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import odgs.listener.ExplorerNodeModifyListener;

public class Directory implements ExplorerNode, Serializable, Comparable
{
	private int uid;
	private String name;
	private String path;
	private String owner;
	private int permission;
	transient private List<ExplorerNode> nodes = new ArrayList<ExplorerNode>();
	transient private List<ExplorerNodeModifyListener> directoryModifyListeners  = new ArrayList<ExplorerNodeModifyListener>();
	
	public Directory(String name, String path)
	{
		this.name = name;
		this.path = path;
	}

	public Directory(String name)
	{
		this(name, "");
	}

	public Directory(int pk)
	{
		uid = pk;
	}

	public Directory(int uid, String name, String path, String owner, int permission)
	{
		this.uid = uid;
		this.name = name;
		this.path = path;
		this.owner = owner;
		this.permission = permission;
	}

	public void add(ExplorerNode node) 
	{
		if(nodes == null)
			nodes = new ArrayList<ExplorerNode>();

		//Collections.sort(nodes);

		if(node.getPath().equals(path + name + "/") || node.getPath().equals(path+name))
		{
			nodes.add(node);
		}
	}
	
	public boolean canChildren()
	{
		return true;
	}
	
	public String getName()
	{
		return name;
	}
	
	public String getOwner()
	{
		return owner;
	}

	public String getPath()
	{
		return path;
	}

	public int getPermission()
	{
		return permission;
	}

	public int getTotalDirectorySize()
	{
		int count = 1;
		for(ExplorerNode node : nodes)
		{
			if(node.canChildren())
				count += ((Directory)node).getTotalDirectorySize();
		}
		return count;
	}

	private void nodifyModifyEvent()
	{
		if(directoryModifyListeners != null)
		{
			for(ExplorerNodeModifyListener l : directoryModifyListeners)
			{
				l.modified(this);
			}
		}
	}

	public void setName(String name)
	{
		this.name = name;

		if(nodes != null)
		{
			List<ExplorerNode> list = getNodesShopshot();
			for (ExplorerNode node : list)
			{
				node.setPath(path + name + "/");
			}
		}
		nodifyModifyEvent();
	}

	private List<ExplorerNode> getNodesShopshot()
	{
		if(nodes != null)
			return new ArrayList<ExplorerNode>(nodes);
		else
			return new ArrayList<ExplorerNode>();
	}

	public void setOwner(String owner)
	{
		this.owner = owner;
		nodifyModifyEvent();
	}

	public void setPath(String path)
	{
		this.path = path;
		if(nodes != null)
		{
			List<ExplorerNode> list = getNodesShopshot();
			for (ExplorerNode node : list)
			{
				node.setPath(path + name + "/");
			}
		}
		nodifyModifyEvent();
	}

	public void setPermission(int permission)
	{
		this.permission = permission;
		nodifyModifyEvent();
	}

	public void remove(ExplorerNode node)
	{
		nodes.remove(node);
	}

	public Directory clones()
	{
		Directory dir = new Directory(name);
		dir.setPath(path);
		dir.setOwner(owner);
		dir.setPermission(permission);

		if(nodes != null)
		{
			List<ExplorerNode> copiedNodes = new ArrayList<ExplorerNode>();
			for(ExplorerNode n : nodes)
			{
				copiedNodes.add(n.clones());
			}
			dir.setNodes(copiedNodes);
		}
		
		if(directoryModifyListeners != null)
			dir.setDirectoryModifyListeners(directoryModifyListeners);
		
		return dir;
	}

	private void setDirectoryModifyListeners(List<ExplorerNodeModifyListener> directoryModifyListeners)
	{
		this.directoryModifyListeners = directoryModifyListeners;
	}

	private void setNodes(List<ExplorerNode> nodes)
	{
		this.nodes = nodes;
	}

	public void addExplorerNodeModifyListener(ExplorerNodeModifyListener listener)
	{
		if(directoryModifyListeners == null)
			directoryModifyListeners = new ArrayList<ExplorerNodeModifyListener>();
		directoryModifyListeners.add(listener);
	}

	public int getTotalContentsSize()
	{
		int count = 0;
		for(ExplorerNode node : nodes)
		{
			if(node.canChildren())
				count += ((Directory)node).getTotalContentsSize();
			else
				count++;
		}
		return count;
	}

	public Directory getDirectory(String position)
	{
		if(position.equals(path + name))
		{
			return this;
		}
		else if(position.equals(path + name + "/"))
		{
			return this;
		}
		else
		{
			if(nodes != null)
			{
				for(ExplorerNode n : nodes)
				{
					if(n.canChildren())
					{
						Directory dir = ((Directory) n);
						Directory temp = dir.getDirectory(position);
						if(temp != null)
							return temp;
					}
				}
			}
		}
		return null;
	}

	public List<Directory> getDirectorys()
	{
		List<Directory> list = new ArrayList<Directory>();
		if(nodes == null)
			nodes = new ArrayList<ExplorerNode>();
		
		for(ExplorerNode node : nodes)
		{
			if(node.canChildren())
				list.add((Directory) node);
		}
		return list;
	}

	public List<Contents> getContents()
	{
		List<Contents> list = new ArrayList<Contents>();
		for(ExplorerNode node : nodes)
		{
			if(!node.canChildren())
				list.add((Contents) node);
		}
		return list;
	}

	public ExplorerNode getAt(String name)
	{
		for (ExplorerNode node : nodes)
		{
			if(node.getName().equals(name))
				return node;
		}
		return null;
	}

	public int getDirectorySize()
	{
		int count = 0;

		if(nodes == null)
			nodes = new ArrayList<ExplorerNode>();
		
		for (ExplorerNode node : nodes)
		{
			if(node.canChildren())
				count++;
		}
		return count;
	}

	public int getContentsSize()
	{
		int count = 0;
		for (ExplorerNode node : nodes)
		{
			if(!node.canChildren())
				count++;
		}
		return count;
	}

	public int getNodeSize()
	{
		return nodes.size();
	}
	
	@Override
	public boolean equals(Object o)
	{
		if (o instanceof Directory)
		{
			Directory dir = ((Directory)o);
			if(dir.getPath().equals(path) && dir.getName().equals(name))
				return true;
		}
		return false;
	}

	public ExplorerNode getExplorerNode(int index)
	{
		return nodes.get(index);
	}

	public List<ExplorerNode> getNodes()
	{
		return nodes;
	}

	public ExplorerNode getDirectory(int index)
	{
		List<Directory> dirs = getDirectorys();
		return dirs.get(index);
	}

	public boolean canMakeDirectory(String name)
	{
		for(ExplorerNode node : nodes)
		{
			if(node.getName().equals(name))
				return false;
		}
		return true;
	}
	
	@Override
	public String toString()
	{
		return name;
	}

	public boolean canRemoveDirectory(String name)
	{
		for(ExplorerNode node : nodes)
		{
			if(node.getName().equals(name))
				return true;
		}
		return false;
	}

	public boolean isNode(String name)
	{
		for (ExplorerNode node : nodes)
		{
			if(node.canChildren())
			{
				if(node.getName().equals(name))
					return true;
			}
			else
			{
				String temp;
				if(name.contains("."))
					temp = node.getName() + "." + node.getType();
				else
					temp = node.getName();
				if(temp.equals(name))
					return true;
			}
		}
		return false;
	}

	public ExplorerNode getNode(String name)
	{
		for (ExplorerNode node : nodes)
		{
			if(node.canChildren())
			{
				if(node.getName().equals(name))
					return node;
			}
			else
			{
				String temp;
				if(name.contains("."))
					temp = node.getName() + "." + node.getType();
				else
					temp = node.getName();
				if(temp.equals(name))
					return node;
			}
		}
		return null;
	}

	public String getType()
	{
		return null;
	}

	public int compareTo(Object arg0)
	{
		Directory dir = (Directory) arg0;
		return name.compareTo(dir.getName());
	}

	public List<ExplorerNode> findByName(String name) {
		List<ExplorerNode> result = new ArrayList<ExplorerNode>();
		List<ExplorerNode> list = getNodesShopshot();
		for(ExplorerNode explorerNode : list) {
			if(explorerNode.canChildren())
			{
				Directory dir = (Directory) explorerNode;
				result.addAll(dir.findByName(name));
			}
			if(explorerNode.getName().matches("(?i).*" + name + ".*"))
			{
				result.add(explorerNode);
			}
		}
		return result;
	}

	public List<ExplorerNode> findByType(String type) {
		List<ExplorerNode> result = new ArrayList<ExplorerNode>();
		List<ExplorerNode> list = getNodesShopshot();
		for(ExplorerNode explorerNode : list) {
			if(explorerNode.canChildren())
			{
				Directory dir = (Directory) explorerNode;
				result.addAll(dir.findByType(type));
			}
			else
			{
				if(explorerNode.getType().matches("(?i).*" + type + ".*"))
				{
					result.add(explorerNode);
				}
			}
		}
		return result;
	}

	public int getUid() {
		return uid;
	}

	public void setUid(int pk) {
		uid = pk;
	}
}